package com.ziq.zcamp.view

import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.util.TypedValue
import android.view.*
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.core.view.NestedScrollingChild2
import androidx.core.view.NestedScrollingChild3
import androidx.core.view.NestedScrollingChildHelper
import androidx.core.view.ViewCompat
import com.ziq.base.extension.click
import com.ziq.zcamp.R


class StatusView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr), NestedScrollingChild2, NestedScrollingChild3 {

    companion object{
        const val IDLE = 0
        const val LOADING = 1
        const val NO_DATA = 2
        const val NET_ERROR = 3
    }

    private val loadingView : LoadingView
    private val llStatus : View
    private val ivStatus : ImageView
    private val tvStatus : TextView
    private val btnAction : TextView
    private val mTouchSlop : Int

    init {
        View.inflate(context, R.layout.view_status, this)
        visibility = View.GONE
        loadingView = findViewById(R.id.loading_view)
        llStatus = findViewById(R.id.ll_status)
        ivStatus = findViewById(R.id.iv_status)
        tvStatus = findViewById(R.id.tv_status)
        btnAction = findViewById(R.id.btn_action)

        isNestedScrollingEnabled = true

        val vc = ViewConfiguration.get(context)
        mTouchSlop = vc.scaledTouchSlop
    }

    fun setStatus(
        status: Int,
        @ColorInt backgroundColor: Int? = null,
        isCenter: Boolean = true,
        marginTop: Int = 0,
        @DrawableRes imgSrc: Int? = null,
        imgHeight: Int? = null,
        imgWidth: Int? = null,
        msg: String? = null,
        textSize: Float? = null,
        textColor: Int? = null,
        updateActionBtn: ((btnAction: TextView) -> Unit)? = null,
    ){

        if(backgroundColor != null){
            setBackgroundColor(backgroundColor)
        } else {
            setBackgroundColor(Color.TRANSPARENT)
        }

        if(isCenter){
            val params = llStatus.layoutParams as FrameLayout.LayoutParams
            params.gravity = Gravity.CENTER
            llStatus.layoutParams = params
        } else {
            val params = llStatus.layoutParams as FrameLayout.LayoutParams
            params.gravity = Gravity.NO_GRAVITY
            params.topMargin = marginTop
            llStatus.layoutParams = params
        }

        if(imgSrc != null){
            ivStatus.setImageResource(imgSrc)
        }

        if(imgHeight != null && imgWidth != null){
            val params = ivStatus.layoutParams as ViewGroup.LayoutParams
            params.height = imgHeight
            params.width = imgWidth
            ivStatus.layoutParams = params
        } else {
            val params = ivStatus.layoutParams as ViewGroup.LayoutParams
            params.height = ViewGroup.LayoutParams.WRAP_CONTENT
            params.width = ViewGroup.LayoutParams.WRAP_CONTENT
            ivStatus.layoutParams = params
        }

        tvStatus.text = msg?:""
        if(textSize != null){
            tvStatus.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize)
        }
        if(textColor != null){
            tvStatus.setTextColor(textColor)
        }
        btnAction.click { }
        btnAction.setText(R.string.click_to_retry)
        btnAction.setTextColor(Color.parseColor("#6e5f55"))
        btnAction.setBackgroundResource(R.drawable.bg_status_view_btn_2dp)
        if(updateActionBtn == null){
            btnAction.visibility = View.GONE
        } else {
            btnAction.visibility = View.VISIBLE
            updateActionBtn?.invoke(btnAction)
        }
        isClickable = false

        when(status){
            IDLE -> {
                visibility = View.GONE
                llStatus.visibility = View.GONE
                loadingView.visibility = View.GONE
                loadingView.stopAnim()
                btnAction.visibility = View.GONE
            }
            LOADING -> {
                visibility = View.VISIBLE
                llStatus.visibility = View.GONE
                loadingView.visibility = View.VISIBLE
                btnAction.visibility = View.GONE
                loadingView.startAnim()
            }
            NO_DATA -> {
                visibility = View.VISIBLE
                llStatus.visibility = View.VISIBLE
                loadingView.visibility = View.GONE

                if(backgroundColor == null){
                    setBackgroundColor(Color.parseColor("#fff6f6f6"))
                }

                if(imgSrc == null){
                    ivStatus.setImageResource(R.drawable.pic_no_content)
                }

                if(msg == null){
                    tvStatus.setText(R.string.view_status_no_data)
                }
                loadingView.stopAnim()
                isClickable = true
            }
            NET_ERROR -> {
                visibility = View.VISIBLE
                llStatus.visibility = View.VISIBLE
                loadingView.visibility = View.GONE

                if(backgroundColor == null){
                    setBackgroundColor(Color.parseColor("#fff6f6f6"))
                }

                if(imgSrc == null){
                    ivStatus.setImageResource(R.drawable.pic_no_network)
                }

                if(msg == null){
                    tvStatus.setText(R.string.view_status_net_error)
                }
                loadingView.stopAnim()
                isClickable = true
            }
        }
    }

    private var mDownMotionX = 0
    private var mDownMotionY = 0
    private var mLastMotionY = 0
    private val mScrollOffset = IntArray(2)
    private val mScrollConsumed = IntArray(2)
    private var isDragging = false

    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.getActionMasked()) {
            MotionEvent.ACTION_DOWN -> {
                isDragging = false
                mDownMotionX = event.rawX.toInt()
                mDownMotionY = event.rawY.toInt()

                mLastMotionY = event.rawY.toInt()
            }
            MotionEvent.ACTION_MOVE -> {
                val x = event.rawX.toInt()
                val y = event.rawY.toInt()
                var deltaY = mLastMotionY - y
                mLastMotionY = y

                val dx: Int = x - mDownMotionX
                val dy: Int = y - mDownMotionY
                if((Math.abs(dy) > Math.abs(dx)) || isDragging) {
                    isDragging = true
                    parent?.requestDisallowInterceptTouchEvent(true)
                    if (startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_TOUCH) && dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset, ViewCompat.TYPE_TOUCH)) {
                        deltaY -= mScrollConsumed[1]
                    }
                    mScrollConsumed[0] = 0
                    mScrollConsumed[1] = 0
                    dispatchNestedScroll(0, deltaY, 0, deltaY, mScrollOffset, ViewCompat.TYPE_TOUCH, mScrollConsumed)
                } else {
                    parent?.requestDisallowInterceptTouchEvent(false)
                }
            }
            MotionEvent.ACTION_UP -> {
                //停止嵌套滑动
                parent?.requestDisallowInterceptTouchEvent(false)
                stopNestedScroll(ViewCompat.TYPE_TOUCH)
            }
            MotionEvent.ACTION_CANCEL -> {
                parent?.requestDisallowInterceptTouchEvent(false)
                stopNestedScroll(ViewCompat.TYPE_TOUCH)
            }

        }
        return true
    }

    private var mScrollingChildHelper: NestedScrollingChildHelper? = null
    private fun getScrollingChildHelper(): NestedScrollingChildHelper? {
        if (mScrollingChildHelper == null) {
            mScrollingChildHelper = NestedScrollingChildHelper(this)
        }
        return mScrollingChildHelper
    }


    // NestedScrollingChild
    override fun setNestedScrollingEnabled(enabled: Boolean) {
        getScrollingChildHelper()!!.isNestedScrollingEnabled = enabled
    }

    override fun isNestedScrollingEnabled(): Boolean {
        return getScrollingChildHelper()!!.isNestedScrollingEnabled
    }

    override fun startNestedScroll(axes: Int): Boolean {
        return getScrollingChildHelper()!!.startNestedScroll(axes)
    }

    override fun startNestedScroll(axes: Int, type: Int): Boolean {
        return getScrollingChildHelper()!!.startNestedScroll(axes, type)
    }

    override fun stopNestedScroll() {
        getScrollingChildHelper()!!.stopNestedScroll()
    }

    override fun stopNestedScroll(type: Int) {
        getScrollingChildHelper()!!.stopNestedScroll(type)
    }

    override fun hasNestedScrollingParent(): Boolean {
        return getScrollingChildHelper()!!.hasNestedScrollingParent()
    }

    override fun hasNestedScrollingParent(type: Int): Boolean {
        return getScrollingChildHelper()!!.hasNestedScrollingParent(type)
    }

    override fun dispatchNestedScroll(
        dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int,
        dyUnconsumed: Int, offsetInWindow: IntArray?
    ): Boolean {
        return getScrollingChildHelper()!!.dispatchNestedScroll(
            dxConsumed, dyConsumed,
            dxUnconsumed, dyUnconsumed, offsetInWindow
        )
    }

    override fun dispatchNestedScroll(
        dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int,
        dyUnconsumed: Int, offsetInWindow: IntArray?, type: Int
    ): Boolean {
        return getScrollingChildHelper()!!.dispatchNestedScroll(
            dxConsumed, dyConsumed,
            dxUnconsumed, dyUnconsumed, offsetInWindow, type
        )
    }

    override fun dispatchNestedScroll(
        dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int,
        dyUnconsumed: Int, offsetInWindow: IntArray?, type: Int, consumed: IntArray
    ) {
        getScrollingChildHelper()!!.dispatchNestedScroll(
            dxConsumed, dyConsumed,
            dxUnconsumed, dyUnconsumed, offsetInWindow, type, consumed
        )
    }

    override fun dispatchNestedPreScroll(
        dx: Int,
        dy: Int,
        consumed: IntArray?,
        offsetInWindow: IntArray?
    ): Boolean {
        return getScrollingChildHelper()!!.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)
    }

    override fun dispatchNestedPreScroll(
        dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?,
        type: Int
    ): Boolean {
        return getScrollingChildHelper()!!.dispatchNestedPreScroll(
            dx, dy, consumed, offsetInWindow,
            type
        )
    }

    override fun dispatchNestedFling(
        velocityX: Float,
        velocityY: Float,
        consumed: Boolean
    ): Boolean {
        return getScrollingChildHelper()!!.dispatchNestedFling(velocityX, velocityY, consumed)
    }

    override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float): Boolean {
        return getScrollingChildHelper()!!.dispatchNestedPreFling(velocityX, velocityY)
    }

}

data class StatusViewData(val status: Int, var action:View.OnClickListener? = null)